/**
 * 
 */
package com.kddi.muldev.op;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLEncoder;
import java.util.Properties;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openid4java.message.ParameterList;

/**
 * @author liuqia
 *
 */
public class ProviderAuthenticationServlet extends HttpServlet {

	private static final long serialVersionUID = 5968004888474964214L;
	
	private static final Log LOG = LogFactory.getLog(ProviderAuthenticationServlet.class);

	private ServletContext context;
	
	public static final String DATA_FILE = "/opt/tomcat/openid_registration_info.properties";
	
	/**
	 * {@inheritDoc}
	 */
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		context = config.getServletContext();
		LOG.debug("context: " + context);
	}

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		this.doPost(req, resp);
	}

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		HttpSession session = request.getSession();
		ParameterList requestp=(ParameterList) session.getAttribute("parameterlist");
	    String openidrealm=requestp.hasParameter("openid.realm") ? requestp.getParameterValue("openid.realm") : null;
	    String openidreturnto=requestp.hasParameter("openid.return_to") ? requestp.getParameterValue("openid.return_to") : null;
	    String openidclaimedid=requestp.hasParameter("openid.claimed_id") ? requestp.getParameterValue("openid.claimed_id") : null;
	    String openididentity=requestp.hasParameter("openid.identity") ? requestp.getParameterValue("openid.identity") : null;
	    
	    response.setCharacterEncoding("UTF-8");
	    
	    if ( checkOpenID(request, response, openididentity) ) {
		    if (request.getParameter("action") == null || request.getAttribute("retry")!=null) { // Display login page
		    	String site=(String) (openidrealm == null ? openidreturnto : openidrealm);
		    	writeLoginResponse(request, response, openidclaimedid, openididentity, site);
		    }else{ // Process login request
		    	 if (checkLogin(request, openididentity)) {
		    		 session.setAttribute("authenticatedAndApproved", Boolean.TRUE); 
		    		 request.setAttribute("_action", "complete");
		    		 RequestDispatcher rd = request.getRequestDispatcher("/auth");
		    		 rd.forward(request, response);
		    	 }else{
		    		 request.setAttribute("retry", Boolean.TRUE);
		    		 RequestDispatcher rd = request.getRequestDispatcher("/login");
		    		 rd.forward(request, response);
		    	 }
		    }
	    }else{
	    	RequestDispatcher rd = request.getRequestDispatcher("/register");
   		 	rd.forward(request, response);
	    }
	}

	/**
	 * Check OpenID
	 * @param request
	 * @param response
	 * @param openididentity
	 * @return
	 */
	private boolean checkOpenID(HttpServletRequest request,
			HttpServletResponse response, String openididentity) {
		Properties props = new Properties();
		boolean result = false;
		File file = FileUtils.getFile(DATA_FILE);
		if (file.exists()) {
			try {
				props.load(new FileInputStream(DATA_FILE));
				result = props.containsKey(encodeString(openididentity));
			} catch (IOException e) {
				LOG.warn(e.getMessage(), e);
			}
		}
		return result;
	}

	/**
	 * Check login
	 * @param request
	 * @return boolean
	 * @throws IOException 
	 */
	private boolean checkLogin(HttpServletRequest request, String openid) throws IOException {
		String loginid = encodeString(request.getParameter("loginid"));
		String password = encodeString(request.getParameter("password"));
		Properties props = new Properties();
		props.load(new FileInputStream(DATA_FILE));
		String info = props.getProperty(encodeString(openid), ",,,,,,,,,,,");
		String[] infoArr = info.split(",",12);
		if (infoArr[0].equals(loginid) && infoArr[1].equals(password)) {
			return true;
		}else{
			return false;
		}
	}

	/**
	 * Write Login Response
	 * @param response
	 * @param openidclaimedid
	 * @param openididentity
	 * @param site
	 * @throws IOException 
	 */
	private void writeLoginResponse(HttpServletRequest request, HttpServletResponse response, String openidclaimedid, String openididentity, 
			String site) throws IOException {
		response.setContentType("text/html");
		StringBuilder sb = new StringBuilder();
		if (StringUtils.isNotEmpty(openidclaimedid)) {
			sb.append("<html><head></head><body style='background-color:#ffffaa;'><strong>ClaimedID:</strong> <pre>"+openidclaimedid+"</pre><br/>");
		}
		sb.append("<strong>Identity:</strong> <pre>"+ openididentity + "</pre><br/>");
		sb.append("<strong>Site:</strong> <pre>" + site + "</pre><br/>");
		if (request.getAttribute("retry")!=null) {
			sb.append("<h4 style='color:red'>LoginId or Password is wrong!</h4>");
		}
		sb.append("<form action='"+(context.getContextPath())+"/login' name='loginForm' method='POST' >");
		sb.append("<table><tr><td>LoginId:</td><td><input type='text' name='loginid' size='60' value='"
				+(request.getParameter("loginid")==null?"":convertCharset(request.getParameter("loginid")))
				+"' /></td></tr>");
		sb.append("<tr><td>Password:</td><td><input type='password' name='password' size='60' value='"
				+(request.getParameter("password")==null?"":convertCharset(request.getParameter("password")))
				+"' /></td></tr></table>");
		sb.append("<input type='submit' value='Login' name='action' /></form></body></html>");
		String respText = sb.toString();
		response.setContentLength(respText.getBytes("UTF-8").length);
		Writer out = response.getWriter();
		out.write(respText);
		response.flushBuffer();
	}
	
	/**
	 * Convert Charset
	 * @param str String
	 * @return String
	 */
	private String convertCharset(String str) {
		if (StringUtils.isBlank(str)) {
			return "";
		}
		try {
			return new String(str.getBytes("ISO-8859-1"), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			LOG.warn(e.getMessage(), e);
			return str;
		}
	}
	
	/**
	 * encodeString
	 * @param str
	 * @return
	 */
	private String encodeString(String str) {
		try {
			return URLEncoder.encode(str,"ISO-8859-1");
		} catch (UnsupportedEncodingException e) {
			LOG.warn(e.getMessage(), e);
			return "";
		}
	}

}
